package com.rm.zeyou.util.QRcode;


import cn.hutool.extra.qrcode.QrCodeUtil;
import com.freewayso.image.combiner.ImageCombiner;
import com.freewayso.image.combiner.enums.OutputFormat;
import com.freewayso.image.combiner.enums.ZoomMode;
import com.google.zxing.EncodeHintType;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.rm.zeyou.util.uploadUtil.AliOSSUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class QRcodeUtil {
    //    @Resource(name = "cosServiceImpl")
//    private OsService ossService;
    @Value(value = "${spring.application.name}")
    private String applicationName;

    @Resource
    private AliOSSUtil aliOSSUtil;

    /**
     * 生成二维码方法
     *
     * @param width  二维码宽
     * @param height 二维码高
     * @param text   二维码内容(二维码可以是任何英文字母加数字生成的二维码)
     * @return url 二维码地址
     */
    public String getQRCodeImage(String text, Integer width, Integer height) throws IOException {
        // 生成唯一文件名并指定为 PNG 格式
        String uniqueFileName = System.currentTimeMillis() + ".png";
        // 确保 QrCodeUtil.generate 支持 PNG 格式（这通常是默认的）
        BufferedImage generate = QrCodeUtil.generate(text, width, height);

        // 假设 aliOSSUtil.uploadFile 支持 PNG 格式
        return aliOSSUtil.uploadFile(bufferedImageToInputStream(generate), uniqueFileName);
    }

    private InputStream bufferedImageToInputStream(BufferedImage image) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos); // 可以根据需要更改为jpg或其他格式
        byte[] imageBytes = baos.toByteArray();
        return new ByteArrayInputStream(imageBytes);
    }

    private Map<EncodeHintType, Object> getEncodeHints() {

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        return hints;
    }


    /**
     * 拼接图片
     *
     * @param bgImageUrl 背景图（url）
     * @param qrCodeUrl  二维码（file协议）
     * @param inviteUrl  邀请链接
     * @return map
     * @throws Exception
     */
    public Map<String, String> drawImage(String bgImageUrl, String qrCodeUrl, String inviteUrl) throws Exception {
        // 创建合成器（指定背景图和输出格式，整个图片的宽高和相关计算依赖于背景图，所以背景图的大小是个基准）
        ImageCombiner combiner = new ImageCombiner(bgImageUrl, 1000, 1400, ZoomMode.WidthHeight, OutputFormat.PNG);  // v1.1.4之后可以指定背景图新宽高了（不指定则默认用图片原宽高）

        // 针对背景和整图的设置
        combiner.setBackgroundBlur(30);     // 设置背景高斯模糊（毛玻璃效果）
        combiner.setCanvasRoundCorner(100); // 设置整图圆角（输出格式必须为PNG）
        combiner.setQuality(.8f);           // 设置图片保存质量（0.0~1.0，Java9以下仅jpg格式有效）

        // 二维码（强制按指定宽度、高度缩放）
        combiner.addImageElement(qrCodeUrl, 700, 1120, 160, 160, ZoomMode.WidthHeight);

        combiner.addTextElement("邀请好友", Font.BOLD, 30, 120, 1120).setSpace(.2f)  // 字间距
                .setStrikeThrough(false) // 删除线
                .setColor(Color.BLACK)
                //.setAlpha(.8f) //透明度（0.0~1.0）
                //.setDirection(Direction.RightLeft) //绘制方向（从右到左，用于需要右对齐场景）
                .setAutoBreakLine(837, 2, 60);      // 自动换行（还有一个LineAlign参数可以指定对齐方式）

        // 内容（设置文本自动换行，需要指定最大宽度（超出则换行）、最大行数（超出则丢弃）、行高）
        combiner.addTextElement("通过扫描图片二维码或者复制链接,分享给好友。", Font.BOLD, 25, 120, 1200).setSpace(.2f) // 字间距
                .setStrikeThrough(false)// 删除线
                .setColor(Color.BLACK)
                .setAutoBreakLine(837, 2, 60);      // 自动换行（还有一个LineAlign参数可以指定对齐方式）

        // 商品图（设置坐标、宽高和缩放模式，若按宽度缩放，则高度按比例自动计算）
        //combiner.addImageElement(productImageUrl, 0, 80, 847, 1250, ZoomMode.WidthHeight).setCenter(true)        // 居中绘制（会忽略x坐标，改为自动计算）
        //        .setRoundCorner(46);   // 设置圆角

        // 头像（圆角设置一定的大小，可以把头像变成圆的）
        // combiner.addImageElement(avatar, 200, 1200)
        //         .setRoundCorner(200);   //圆角

        // 水印（设置透明度，0.0~1.0）
        // combiner.addImageElement(waterMark, 630, 1200)
        //         .setAlpha(.8f)          //透明度（0.0~1.0）
        //         .setRotate(45)          //旋转（0~360）
        //         .setBlur(20) ;        //高斯模糊(1~100)
        //         .setRepeat(true, 100, 50);    //平铺绘制（可设置水平、垂直间距）

        // 加入圆角矩形元素（版本>=1.2.0），作为二维码的底衬
        // combiner.addRectangleElement(700, 1480, 300, 300)
        //         .setColor(Color.WHITE)
        //         .setRoundCorner(50)     //该值大于等于宽高时，就是圆形，如设为300
        //         .setAlpha(.8f)
        //         .setGradient(Color.yellow,Color.blue, GradientDirection.LeftRight)  //颜色渐变
        //     .setBorderSize(5);      //设置border大小就是空心，不设置就是实心

        // 执行图片合并
        combiner.combine();

        String path = applicationName + System.currentTimeMillis() + ".png";

        //上传oss
        String s = aliOSSUtil.uploadFile(combiner.getCombinedImageStream(), path);
        //String uploadFile = JSCHUploadFile.uploadFile(combiner.getCombinedImageStream(), path);
        HashMap<String, String> map = new HashMap<>(3);
        //合成后的图片地址
        map.put("path", s);
        //邀请链接
        map.put("url", inviteUrl);
        //二维码
        map.put("qrCode", qrCodeUrl);
        return map;
    }

    /**
     * 上传到本地
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static String uploadImg(MultipartFile file) throws IOException {
        // 2.根据时间戳创建新的文件名，这样即便是第二次上传相同名称的文件，也不会把第一次的文件覆盖了
        String fileName = System.currentTimeMillis() + file.getOriginalFilename();
        // 3.通过req.getServletContext().getRealPath("") 获取当前项目的真实路径，然后拼接前面的文件名
        // String destFileName = "C:\\HBuilderX\\HBuilderProjects\\TP\\"+fileName;
        // String destFileName = ResourceUtils.getURL("classpath:").getPath()+"/static/"+fileName;
        String destFileName = System.getProperty("user.dir") + "/static/" + fileName;
        // 4.第一次运行的时候，这个文件所在的目录往往是不存在的，这里需要创建一下目录（创建到了webapp下uploaded文件夹下）
        File destFile = new File(destFileName);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }
        // 5.把浏览器上传的文件复制到希望的位置
        file.transferTo(destFile);
        // 6.把文件名放在model里，以便后续显示用


        return "/static" + "/" + fileName;
    }
}

